package cn.jtfadmin.activiti.controller.rest;

import cn.jtfadmin.activiti.domain.dto.*;
import cn.jtfadmin.activiti.domain.entity.FormDesignEntity;
import cn.jtfadmin.activiti.service.ActModelService;
import cn.jtfadmin.base.dict.dto.DictItemModelDTO;
import cn.jtfadmin.base.lang.common.domain.dto.PageRDTO;
import cn.jtfadmin.base.lang.common.domain.dto.ResultDTO;
import cn.jtfadmin.base.lang.common.utils.RequestUtils;
import cn.jtfadmin.base.lang.config.excel.ExcelWeb;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程设计模块-模型
 * @author jtf
 * @since 0.0.2
 */
@RestController
@Validated
public class ActivitiModelController implements ModelDataJsonConstants {



    @Autowired
    private ActModelService actModelService;

    /**
     * 新增模型
     * @param addPDTO
     * @return 模型id
     */
    @PostMapping(value = "/activiti/model/add")
    public ResultDTO<String> addModel(@Validated @RequestBody ModelAddPDTO addPDTO){
        return ResultDTO.successData(actModelService.addModel(addPDTO).getId());
    }

    /**
     * 编辑id模型
     * @param editPDTO
     * @return 模型id
     */
    @PutMapping(value = "/activiti/model/edit")
    public ResultDTO<String> editModel(@Validated @RequestBody ModelEditPDTO editPDTO){
        return ResultDTO.successData(actModelService.editModel(editPDTO).getId());
    }




    /**
     * 列表查询
     * @param name 名称
     * @param tenantId 租户id
     * @param pageNo 页码
     * @param pageSize 数量
     * @return 模型信息
     */
    @GetMapping(value = "/activiti/model/list")
    public ResultDTO<PageRDTO<ModelDTO>> listModel(@RequestParam(required = false) String name,
                                                   @RequestParam() @NotBlank String tenantId,
                                                    @RequestParam(required = false, defaultValue = "1") Integer pageNo,
                                                   @RequestParam(required = false, defaultValue = "10") Integer pageSize){
        return ResultDTO.successData(actModelService.listModel(name, tenantId, pageNo, pageSize));
    }

    /**
     * 获取模型字典
     * @param tenantId
     * @return
     */
    @GetMapping(value = "/activiti/model/named")
    public ResultDTO<List<DictItemModelDTO>> modelNamed(String tenantId){
        return ResultDTO.successData(actModelService.modelNamed(tenantId));
    }

    /**
     * 按照id删除模型
     * @param id
     * @return
     */
    @DeleteMapping(value = "/activiti/model/delete")
    public ResultDTO<String> deleteModel(@RequestParam(required = true) String id){
        actModelService.deleteModel(id);
        return ResultDTO.success();
    }

    /**
     * 按照ids删除模型
     * @param ids id,id,
     * @return
     */
    @DeleteMapping(value = "/activiti/model/deleteBatch")
    public ResultDTO<String> deleteBatchModel(@RequestParam(required = true) String ids){
        actModelService.deleteBatchModel(ids);
        return ResultDTO.success();
    }



    /**
     * 部署
     * @param id 流程id
     * @return
     */
    @RequestMapping(value = "/activiti/model/deployment", method = RequestMethod.POST)
    public ResultDTO<String> deployModel(@RequestParam(required = true) String id,@RequestParam(required = false) String file) {
        actModelService.deployModel(id,file);
        return ResultDTO.success();
    }



    /**
     * 按照id删除部署信息
     * @param id 部署id
     * @return
     */
    @DeleteMapping(value = "/activiti/deployment/delete")
    public ResultDTO<String> deleteDeployment(@RequestParam(required = true) String id){
        actModelService.deleteDeployment(id);
        return ResultDTO.success();
    }

    /**
     * 按照ids删除部署
     * @param ids id,id,
     * @return
     */
    @DeleteMapping(value = "/activiti/deployment/deleteBatch")
    public ResultDTO<String> deleteBatchDeployment(@RequestParam(required = true) String ids){
        actModelService.deleteBatchDeployment(ids);
        return ResultDTO.success();
    }

    /**
     * 获取流程定义信息
     * @param modelId 模型id
     * @return
     */
    @GetMapping(value = "/activiti/processDefinition/list")
    public ResultDTO<List<ProcessDefinitionDTO>> listDefinition(@RequestParam(required = true)String modelId){
        return ResultDTO.successData(actModelService.listDefinition(modelId));
    }

    /**
     * 删除流程定义信息
     * @param id 流程idid
     * @return
     */
    @DeleteMapping(value = "/activiti/processDefinition/delete")
    public ResultDTO<String> deleteDefinition(@RequestParam(required = true) @NotBlank String id){
        actModelService.deleteDefinition(id);
        return ResultDTO.success();
    }

    /**
     * 修改模型版本号
     * @param id id
     * @param version 版本
     * @return
     */
    @PutMapping(value = "/activiti/model/updateVersion")
    public ResultDTO<String> updateModelVersion(@RequestParam @NotBlank String id, @RequestParam @NotNull Integer version){
        actModelService.updateModelVersion(id, version);
        return ResultDTO.success();
    }

    /**
     * 批量删除流程定义
     * @param ids 定义IDS
     * @return
     */
    @DeleteMapping(value = "/activiti/processDefinition/deleteBatch")
    @Transactional
    public ResultDTO<String> deleteDefinitions(@RequestParam(required = true)String ids){
        String[] strings = StringUtils.delimitedListToStringArray(ids, ",");
        for (String string : strings) {
            if(StringUtils.hasText(string)){
                deleteDefinition(string.trim());
            }
        }
        return ResultDTO.success();
    }

    /**
     * 获取model 图片资源
     * @param id
     */
    @GetMapping(value = "/activiti/model/getPngResource",produces= MediaType.IMAGE_PNG_VALUE)
    public void getModelPngResource(@RequestParam() String id){
        try {
            HttpServletResponse response = RequestUtils.getResponse();
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(actModelService.getModelEditorSourceExtra(id));
        } catch (IOException e) {
            // ignore
        }
    }




    /**
     * 获取进程定义资源
     * @param name 资源名称
     * @param deploymentId 部署id
     */
    @GetMapping(value = "/activiti/processDefinition/resource")
    public void getProcessResource(@RequestParam() @NotBlank String name,@RequestParam @NotBlank String deploymentId) {
        try (InputStream resourceAsStream = actModelService.getProcessResouce(deploymentId,name)) {
            HttpServletResponse response = RequestUtils.getResponse();
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            ServletOutputStream outputStream = response.getOutputStream();
            StreamUtils.copy(resourceAsStream, outputStream);
        } catch (IOException e) {
            // ignore
        }
    }

    /**
     * 导出资源
     * @param ids 进程id
     */
    @GetMapping(value = "/activiti/processDefinition/exportResource")
    public void exportResouce(@RequestParam() @NotBlank String ids){
        OutputStream outputStream = ExcelWeb.addCurrentResposeHeader("流程图资源.zip");
        actModelService.exportResouce(ids, outputStream);
    }


    /**
     * 新增设计表单
     * @param addPDTO
     * @return 模型id
     */
    @PostMapping(value = "/activiti/formDesign/add")
    public ResultDTO<String> addFormDesign(@Validated @RequestBody FormDesignAddPDTO addPDTO){
        return ResultDTO.successData(actModelService.addFormDesign(addPDTO).getId());
    }

    /**
     * 编辑设计表单
     * @param editPDTO
     * @return 模型id
     */
    @PutMapping(value = "/activiti/formDesign/edit")
    public ResultDTO<String> editFormDesign(@Validated @RequestBody FormDesignEditPDTO editPDTO){
        return ResultDTO.successData(actModelService.editFormDesign(editPDTO).getId());
    }




    /**
     * 列表查询
     * @param modelId 模型id
     * @return
     */
    @GetMapping(value = "/activiti/formDesign/list")
    public ResultDTO<List<FormDesignEntity>> listFormDesign(@RequestParam() String modelId
                                                   ){
        return ResultDTO.successData(actModelService.listFormDesign(modelId).stream()
        .map(t->{
            FormDesignEntity e = new FormDesignEntity();
            BeanUtils.copyProperties(t, e, "content");
            return e;
        }).collect(Collectors.toList()));
    }

    /**
     * 按照id删除设计表单
     * @param id
     * @return
     */
    @DeleteMapping(value = "/activiti/formDesign/delete")
    public ResultDTO<String> deleteFormDesign(@RequestParam(required = true) String id){
        actModelService.deleteFormDesign(id);
        return ResultDTO.success();
    }

    /**
     * 按照ids删除设计表单
     * @param ids id,id,
     * @return
     */
    @DeleteMapping(value = "/activiti/formDesign/deleteBatch")
    public ResultDTO<String> deleteBatchFormDesign(@RequestParam(required = true) String ids){
        actModelService.deleteBatchFormDesign(ids);
        return ResultDTO.success();
    }

    /**
     * 获取表单设计内容
     * @param id
     * @return
     */
    @GetMapping(value = "/activiti/formDesign/getDesignContent", produces = MediaType.TEXT_HTML_VALUE)
    public ResultDTO<String> getFormDesignContent(@RequestParam String id){
        Optional<FormDesignEntity> optional = actModelService.getFormDesignById(id);
        FormDesignEntity entity = optional.get();
        String content = entity.getContent();
        if(content == null){
            content = "";
        }
        return ResultDTO.successData(content);
    }

    /**
     * 修改表单设计器
     * @param id 表单设计器id
     * @param content 内容
     */
    @PostMapping(value = "/activiti/formDesign/updateFormDesignContent")
    public ResultDTO<String> updateFormDesignContent(@RequestParam String id, @RequestParam String content){

        actModelService.updateFormDesignContent(id, content);
        return ResultDTO.success();
    }
}

